package tsing.good_simple.abstractLock.singleProjectAbstract;


import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;

/**
 * @Date 2024/11/25 14:40
 * @Author Tsing
 *
 * 模板方法的加锁的实现
 */
public class LockTemplateSupport {


    private final Cache<String, Lock> lockCache;

    private final ReentrantLock lock = new ReentrantLock();


    // 使用guava的缓存工具
    public LockTemplateSupport (){
        lockCache = CacheBuilder.newBuilder()
                .expireAfterAccess(10,TimeUnit.MINUTES)
                .build();
    }



    /**
     * 使用Runnable传递方法
     @param key
     * @param timeOut
     * @param timeUnit
     * @param task
     * @throws InterruptedException
     */
    public void executeWithLock(String key ,long timeOut,TimeUnit timeUnit,Runnable task) throws InterruptedException {
        Lock lock = lockCache.getIfPresent(key);
        if(lock==null){
            synchronized (this){
                lock = lockCache.getIfPresent(key);
                if (lock == null) {
                    lock = new ReentrantLock();
                    lockCache.put(key, lock);
                }
            }

        }
        boolean lockFlag = lock.tryLock(timeOut, timeUnit);
        if(!lockFlag){
            return ;
        }
        try {
            // 加锁成功,执行业务方法
            task.run();
        } finally {
            // 解锁
            lock.unlock();
        }

    }


    /**
     * 使用Runnable传递方法
     * 使用reentryLock锁
     * @param timeOut
     * @param timeUnit
     * @param task
     * @throws InterruptedException
     */
    public void executeWithLock(long timeOut,TimeUnit timeUnit,Runnable task) throws InterruptedException {
        boolean lockFlag = lock.tryLock(timeOut, timeUnit);
        if(!lockFlag){
            return ;
        }
        try {
            // 加锁成功,执行业务方法
          task.run();
        } finally {
            // 解锁
            lock.unlock();
        }

    }


    /**
     * 使用Supplier 传递方法，可获得方法返回值
     * @param timeOut
     * @param timeUnit
     * @param task
     * @return
     * @param <T>
     * @throws InterruptedException
     */
    public <T> T executeWithLock(long timeOut, TimeUnit timeUnit, Supplier<T> task) throws InterruptedException {
        boolean lockFlag = lock.tryLock(timeOut, timeUnit);
        if(!lockFlag){
            // 返回空或者抛异常
            return null;
        }
        try {
            // 加锁成功,执行业务方法
           return  task.get();
        } finally {
            // 解锁
            lock.unlock();
        }

    }

}
